view
<template>
	<view class="task-box">
		<uv-navbar :title="pageTitle" auto-back bg-color="transparent" placeholder />
		<view class="task-list">
			<view class="tab-row">
				<view v-for="(t, k) in tabs" :key="k" @click="changeTab(k)">
					<text>{{ t.name }}</text>
				</view>
				<view class="actvie" :style="{
            left: actvie * 50 + '%',
          }" />
				<view v-if="actvie == 1" class="task-filter">
					<uv-icon :name="iconFunnel" @click="openFilter" />
				</view>
			</view>
			<scroll-view scroll-y style="height: calc(100% - 150rpx); padding-bottom: 30rpx;" scroll-with-animation
				@scrolltolower="loadMore">
				<view class="task-list-row" v-if="actvie == 0">
					<view class="task-item" v-for="(item, index) in dataList" :key="index" @click="handleDetail(item)"
						:style="{
							'--bgColor': getColor(item.status),
						}">
						<view style="padding: 20rpx 20rpx 20rpx 50rpx">
							<uv-text :text="`${item.projectName}（第${item.cycleNo}期）`" :lines="1" color="#212121"
								size="28rpx" line-height="50rpx" />
							<uv-text :text="item.endTime || item.beginTime" color="#757575" size="24rpx"
								line-height="60rpx" />
							<view class="below" v-if="item.passStatus != 1">存在不合格项</view>
							<uv-line-progress :percentage="item.subPlantRate"
								:active-color="getStatusCOlor(item.status)" />
							<view class="row">
								<uv-icon bold :name="getStatusIcon(item.status)" :label="getStatusLabel(item.status)"
									label-color="#757575" label-size="24rpx" />
								<uv-icon :name="iconMember" size="32rpx" :label="item.userNickName"
									label-color="#757575" space="10rpx" label-size="24rpx" />
							</view>
						</view>
						<view v-if="item.status == 4 && item.projectLeader" class="report-btn"
							@click.stop="handleReport(item)">
							生成报告
						</view>
					</view>
				</view>
				<view class="task-list-row" v-if="actvie == 1">
					<view class="task-item" v-for="(item, index) in dataList" :key="index" @click="handleDetail(item)"
						:style="{
							'--bgColor': getColor(item.status),
						}">
						<view style="padding: 20rpx 20rpx 20rpx 50rpx">
							<uv-text :text="item.name" :lines="1" color="#212121" size="28rpx" line-height="50rpx" />
							<uv-text :text="item.createTime" color="#757575" size="24rpx" line-height="50rpx" />
							<view class="below" v-if="item.passStatus != 1">存在不合格项</view>
							<view class="row">
								<uv-icon :label="`${item.planBeginTime.split(' ')[0]}报告`" label-color="#757575"
									label-size="24rpx" />
								<uv-icon :name="iconMember" size="32rpx" label-color="#757575" space="10rpx"
									:label="item.nickName" label-size="24rpx" />
							</view>
						</view>
					</view>
				</view>
				<uv-load-more v-if="dataList.length > 0" :status="status" class="ss-m-y-30" />
				<uv-empty v-if="dataList.length == 0" margin-top="6vh" :icon="empty"
					:text="`暂无维保${actvie == 0 ? '任务' : '报告'}`" />
			</scroll-view>
		</view>
		<uv-popup ref="popupRef" mode="right" z-index="980" closeable>
			<view class="popup-content">
				<uv-status-bar />
				<uv-text text="数据筛选" color="#757575" size="28rpx" line-height="100rpx" margin="auto 30rpx" />
				<uv-text text="关键字查询" color="#757575" size="28rpx" line-height="80rpx" margin="auto 30rpx" />
				<uv-input v-model="queryParams.keywords" clearable :customStyle="{
            margin: 'auto 30rpx',
            height: '44rpx',
          }" placeholder="输入报告关键词" prefix-icon="search" :prefix-icon-style="{
            fontSize: '44rpx',
            color: '#909399',
          }" />
				<uv-text text="提交时间" color="#757575" size="28rpx" line-height="80rpx" margin="auto 30rpx" />
				<view class="row">
					<view class="row-btn" v-for="(i, k) in times" :key="k" :class="{ active: i.value == time }"
						@click="changeTime(i)">
						{{ i.label }}
					</view>
				</view>
				<uv-text text="自定义时间段" color="#757575" size="28rpx" line-height="80rpx" margin="auto 30rpx" />
				<view class="date-box" @click="handleCalendar">
					<uv-icon name="clock" color="#BDBDBD" size="28rpx" />
					<view v-if="!startTime || !endTime" class="placeholder">选择时间范围</view>
					<view v-else class="date"> {{ startTime }} - {{ endTime }} </view>
				</view>
				<view class="row-bottom">
					<uv-button text="重置" @click="resetQuery" />
					<uv-button text="确定" color="#fff" :custom-style="{
              background: '#4EA770',
            }" @click="handleQuery" />
				</view>
			</view>
		</uv-popup>
		<uv-calendars ref="calendarsRef" mode="range" :round="0" color="#4EA770" confirm-color="#4EA770" allow-same-day
			:date="startTime && endTime ? [startTime, endTime] : ''" @confirm="confirmDate" />
	</view>
</template>
<script setup>
	import {
		ref,
		computed,
		onMounted,
		onBeforeUnmount
	} from "vue";
	import {
		getDateRange
	} from "@/common/mothed.js";
	import {
		onLoad
	} from "@dcloudio/uni-app";
	import {
		taskList,
		reportList,
		generateReport
	} from "@/request/task.js";
	import empty from "@/static/empty.png";
	import iconFunnel from "@/static/icon_funnel.png";
	import iconMember from "@/static/icon_member.png";
	import iconClock from "@/static/home/icon_clock.png";
	import iconSuccess from "@/static/home/icon_success.png";
	import iconProgress from "@/static/home/icon_progress.png";
	import iconWarn from "@/static/home/icon_warn.png";

	const dataList = ref([]); // 项目完成列表
	const actvie = ref(0); // 选中的tab
	const tabs = ref([{
		name: "维保任务"
	}, {
		name: "维保报告"
	}]);
	const popupRef = ref(); // 弹出层ref
	const calendarsRef = ref(); // 日历组件ref
	const time = ref(""); // 选中时间类型
	const startTime = ref(""); // 开始时间
	const endTime = ref(""); // 结束时间
	const queryParams = ref({
		pageNum: 1,
		pageSize: 10,
		endTime: "",
		startTime: "",
		status: -1,
		keywords: "", // 搜索关键词
	});
	const total = ref(0); // 总条数
	const status = ref("loadmore"); // 加载状态
	const times = ref([{
			value: "day",
			label: "今天"
		},
		{
			value: "lastday",
			label: "昨天"
		},
		{
			value: "week",
			label: "本周"
		},
		{
			value: "lastweek",
			label: "上周"
		},
		{
			value: "month",
			label: "本月"
		},
		{
			value: "lastmonth",
			label: "上月"
		},
	]); // 快捷时间列表
	const pageTitle = ref("待处理任务");

	onLoad((e) => {
		if (e.type) {
			actvie.value = Number(e.type || 1) - 1;
			if (e.type == 2) {
				pageTitle.value = "我的报告"
				queryParams.value.status = null;
			}
		}
		getList();
	});

	onMounted(() => {
		uni.$on("taskReport", () => {
			uni.$emit("untreated");
			getList();
		});
	});

	onBeforeUnmount(() => {
		uni.$off("taskReport");
	});

	// 加载更多
	const loadMore = () => {
		if (dataList.value.length < total.value) {
			queryParams.value.pageNum++;
			getList();
		}
	};

	// 获取数据列表
	const getList = () => {
		if (actvie.value == 0) {
			status.value = "loading";
			taskList({
					pageNum: queryParams.value.pageNum,
					pageSize: queryParams.value.pageSize,
				})
				.then((res) => {
					if (res.code == 200) {
						dataList.value = queryParams.value.pageNum == 1 ? res.rows : dataList.value.concat(res
							.rows);
						total.value = res.total;
					}
				}).finally(() => {
					status.value = total.value > dataList.value.length ? "loadmore" : "nomore";
				})
		} else {
			reportList(queryParams.value).then((res) => {
				if (res.code == 200) {
					dataList.value = queryParams.value.pageNum == 1 ? res.data.records : dataList.value.concat(
						res.data.records);
					total.value = res.data.total;
				}
			}).finally(() => {
				status.value = total.value > dataList.value.length ? "loadmore" : "nomore";
			})
		}
	};

	// 切换tab
	const changeTab = (k) => {
		actvie.value = k;
		dataList.value = [];
		queryParams.value.pageNum = 1;
		getList();
	};

	// 生成报告
	const handleReport = (item) => {
		generateReport(item.subPlanId).then((res) => {
			if (res.code == 200) {
				uni.navigateTo({
					url: "/pages/Task/reportDetails?id=" + res.data,
				});
			}
		});
	};

	// 时间类型切换
	const changeTime = (i) => {
		time.value = i.value;
		const range = getDateRange(i.value);
		startTime.value = range[0];
		endTime.value = range[1];
		queryParams.value.startTime = startTime.value + " 00:00:00";
		queryParams.value.endTime = endTime.value + " 23:59:59";
	};

	const handleDetail = (item) => {
		if (actvie.value == 0) {
			uni.navigateTo({
				url: `/pages/Task/select?subPlanId=${item.subPlanId}&projectName=${item.projectName}&cycleNo=${item.cycleNo}`,
			});
		} else {
			uni.navigateTo({
				url: "/pages/Task/reportDetails?id=" + item.id,
			});
		}
	};

	// 选择日期
	const confirmDate = (val) => {
		startTime.value = val.range.before;
		endTime.value = val.range.after;
		queryParams.value.startTime = startTime.value + " 00:00:00";
		queryParams.value.endTime = endTime.value + " 23:59:59";
		time.value = "";
	};

	// 重置查询
	const resetQuery = () => {
		time.value = "";
		startTime.value = "";
		endTime.value = "";
		queryParams.value.startTime = "";
		queryParams.value.endTime = "";
		queryParams.value.keywords = "";
		queryParams.value.pageNum = 1;
		popupRef.value.close();
		getList();
	};

	// 确认查询
	const handleQuery = () => {
		popupRef.value.close();
		dataList.value = [];
		queryParams.value.pageNum = 1;
		getList();
	};

	// 打开筛选弹窗
	const openFilter = () => {
		popupRef.value.open();
	};

	// 打开日历弹窗
	const handleCalendar = () => {
		calendarsRef.value.open();
	};

	// 状态图标
	const getStatusIcon = (status) => {
		switch (status) {
			case 2:
				return iconClock;
			case 3:
				return iconProgress;
			case 4:
				return iconSuccess;
			case 5:
				return iconWarn;
			default:
				return "";
		}
	};

	// 状态图标颜色
	const getStatusCOlor = (status) => {
		switch (status) {
			case 2:
				return "#757575";
			case 3:
				return "#007AFF";
			case 4:
				return "#37B23E";
			case 5:
				return "#FE5353";
			default:
				return "";
		}
	};

	// 状态颜色
	const getColor = (status) => {
		switch (status) {
			case 2:
				return "#f2ce90";
			case 3:
				return "#87BCF5";
			case 4:
				return "#85C889";
			case 5:
				return "#F2AFA5";
			default:
				return "";
		}
	};

	// 状态中文显示
	const getStatusLabel = (status) => {
		switch (status) {
			case 2:
				return "未开始";
			case 3:
				return "进行中";
			case 4:
				return "已完成";
			case 5:
				return "已超时";
			default:
				return "";
		}
	};
</script>
<style lang="scss" scoped>
	.more {
		text-align: center;
	}

	.task-box {
		height: 100vh;
		padding: 40rpx;
		box-sizing: border-box;
		background: linear-gradient(180deg, #ffffff 0%, #50bc7a 100%);

		.task-list {
			height: calc(100vh - 160rpx - var(--status-bar-height));
			background: linear-gradient(180deg, #ace1b5 0%, #fbfbfb 120rpx, #fbfbfb 100%);
			box-shadow: 0 0 20rpx 2rpx rgba(78, 167, 112, 0.16);
			border-radius: 20rpx;
			box-sizing: border-box;
			overflow: auto;

			.tab-row {
				display: flex;
				height: 120rpx;
				position: sticky;
				z-index: 9;
				top: 0;
				background: linear-gradient(180deg, #ace1b5 0%, #fbfbfb 100%);

				view {
					flex: 1;
					display: flex;
					align-items: center;
					justify-content: center;
					color: #212121;
					font-size: 28rpx;

					text {
						z-index: 9;
					}
				}

				.task-filter {
					position: absolute;
					right: 36rpx;
					height: 100%;
					display: flex;
					align-items: center;
				}

				.actvie {
					background: linear-gradient(180deg, #e3f6e6 0%, #fbfbfb 100%);
					box-shadow: inset 0 2rpx 2rpx 2rpx rgba(255, 255, 255, 0.99);
					border-radius: 20rpx 20rpx 0 0;
					position: absolute;
					transition: left 0.3s;
					height: 120rpx;
					width: 50%;

					&::after {
						content: "";
						position: absolute;
						width: 70rpx;
						height: 8rpx;
						background: #4ea770;
						border-radius: 4rpx;
						bottom: 20rpx;
						left: calc(50% - 35rpx);
					}
				}
			}

			.task-list-row {
				margin: 18rpx;

				.task-item {
					--bgColor: #4ea770;
					width: auto;
					min-height: 160rpx;
					background: #f6f6f6;
					border-radius: 20rpx;
					justify-content: space-between;
					margin-bottom: 20rpx;
					box-sizing: border-box;
					overflow: hidden;
					position: relative;

					.below {
						position: absolute;
						top: 81rpx;
						left: 320rpx;
						color: #e21818;
						font-size: 24rpx;
					}

					&::after {
						content: "";
						position: absolute;
						left: 0;
						top: 0;
						bottom: 0;
						width: 20rpx;
						background: var(--bgColor);
					}

					.row {
						margin-top: 12rpx;
						display: flex;

						>view:first-child {
							margin-right: 40rpx;
						}
					}

					.report-btn {
						height: 76rpx;
						display: flex;
						align-items: center;
						justify-content: center;
						border-top: 2rpx solid #dedede;
						color: #757575;
						font-size: 28rpx;

						&:active {
							background-color: #f1f1f1;
						}
					}
				}
			}
		}
	}

	.popup-content {
		width: 600rpx;
		height: 100%;
		position: relative;

		.row {
			display: grid;
			gap: 20rpx;
			grid-template-columns: repeat(3, 1fr);
			padding: 0 30rpx;
			margin-bottom: 40rpx;

			&-btn {
				width: 160rpx;
				height: 66rpx;
				border-radius: 8rpx;
				background-color: #fff;
				border: 2rpx solid #dedede;
				font-size: 28rpx;
				color: #757575;
				display: flex;
				align-items: center;
				justify-content: center;
			}

			.active {
				color: #fff;
				background-color: #4ea770;
				border: 2rpx solid #4ea770;
			}
		}

		.date-box {
			height: 66rpx;
			padding: 12rpx;
			box-sizing: border-box;
			margin: auto 30rpx;
			background: #ffffff;
			border-radius: 8rpx;
			border: 2rpx solid #dedede;
			display: flex;
			align-items: center;

			.placeholder {
				font-size: 28rpx;
				color: #bdbdbd;
				margin-left: 10rpx;
			}

			.date {
				font-size: 28rpx;
				color: #bdbdbd;
				margin-left: 10rpx;
			}
		}

		.row-bottom {
			position: absolute;
			bottom: 0;
			width: 100%;
			display: flex;

			view {
				flex: 1;
			}
		}
	}

	:deep(.uv-popup__content__close--top-right) {
		top: calc(15px + var(--status-bar-height)) !important;
	}
</style>